/*
 * @Author: xiaosihan 
 * @Date: 2024-08-26 22:30:11 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-08-27 11:23:02
 */

import utils from "@utils";
import axios from "axios";
import JSZip from 'jszip';
import { DefaultLoadingManager, Object3D } from "three";
import { ColladaLoader, DRACOLoader, GLTFLoader } from "three/examples/jsm/Addons.js";

const gltfLoader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
gltfLoader.setDRACOLoader(dracoLoader.setDecoderPath('./three_gltf/'));

// 资源列表
const blobs: { [key: string]: string } = {};

// 资源替换
DefaultLoadingManager.setURLModifier((url) => {
    const filename = url.replace(`blob:${location.origin}/`, "").replace(/^\.\//, "");
    const new_url = blobs[filename] || url;
    return new_url;
});

export default async function loadMesh(url: string): Promise<Object3D> {

    const suffix = utils.getSuffix(url);

    const object = await new Promise<Object3D>(async (loadMeshResolve, reject) => {

        switch (suffix) {
            case "zip":
                await new Promise(async (resolve, reject) => {

                    const zipFile = await axios.get(url, { responseType: 'arraybuffer' })
                        .then(response => {
                            const zipFile = new File([response.data], "1.zip", { type: 'application/octet-stream' });
                            return zipFile;
                        });

                    await JSZip.loadAsync(zipFile).then(async (zip) => {
                        for (let filename in zip.files) {
                            if (!zip.files[filename].dir) { // 不读文件夹
                                await zip.file(filename)!.async('blob').then((blob) => {
                                    var blobURL = URL.createObjectURL(blob);
                                    blobs[filename] = blobURL;
                                });
                            }
                        }

                        //如果有gltf文件就加载gltf文件
                        let gltf = Object.keys(zip.files).find(filename => /\.(gltf|glb)$/.test(filename));
                        if (gltf) {
                            const gltfObject3d = await loadMesh(gltf);
                            loadMeshResolve(gltfObject3d);
                        }
                    })
                });
                break;

            case "glb":
            case "gltf":
                const [gltfObject3d] = await Promise.all([
                    gltfLoader.loadAsync(url),
                    new Promise<void>((resolve, reject) => {
                        DefaultLoadingManager.onLoad = () => {
                            resolve();
                        }
                    })
                ]);
                gltfObject3d.scene.animations = gltfObject3d.animations;
                loadMeshResolve(gltfObject3d.scene);
                break;

        }

    });

    return object;

}